<template>
  <AuModal
    v-model="showImportModal"
    :title="t('device_manage.import.title')"
    width="70vw"
    height="70vh"
    :padding="false"
    @handleConfirm="handleConfirm"
  >
    <div class="h-full pt-[16px]">
      <div class="flex justify-between items-center px-[1rem]">
        <el-button type="primary" plain @click="fileInput?.click()"
          >{{ t("device_manage.import.upload_button") }}
        </el-button>
        <input
          ref="fileInput"
          :key="inputKey"
          type="file"
          accept=".xlsx,.xls"
          style="display: none"
          @change="fileChanged"
        />
        <el-button type="primary" link @click="fileDownload"
          >{{ t("device_manage.import.example_download") }}
        </el-button>
      </div>
      <div class="h-[calc(100%_-_40px)]">
        <AuTable ref="tableRef" v-bind="gridOption">
          <template #status_default="{ row }">
            <el-tag :type="row.itemStatus ? 'success' : 'danger'" plain
              >{{
                row.itemStatus
                  ? t("device_manage.import.normal")
                  : t("device_manage.import.abnormal")
              }}
            </el-tag>
          </template>
        </AuTable>
      </div>
    </div>
  </AuModal>
</template>

<script lang="ts">
import {
  computed,
  defineComponent,
  getCurrentInstance,
  nextTick,
  reactive,
  ref,
  watch
} from "vue";
import {
  ACTION_TYPE,
  ObjectProps,
  PropDefines
} from "@/components/AuTable/type";
import { AuTable } from "@/components/AuTable";
import { AuModal } from "@/components/AuModal";
import * as XLSX from "xlsx";
import { RegInt, Unique } from "@/utils/tool";
import { addDeviceEnterList, deviceActivation } from "@/api/factory/device";
import { useI18n } from "vue-i18n";
import {
  DEVICE_ID_LIST,
  DEVICE_TYPE_ENUM,
  DEVICE_TYPE_MATCH
} from "@/utils/constants";

export default defineComponent({
  name: "ExcelImport",
  components: { AuModal, AuTable },
  props: {
    modelValue: {
      type: Boolean,
      default: false
    }
  },
  emit: ["update:modelValue", "confirm"],
  setup(props, { emit }) {
    const { proxy } = getCurrentInstance();
    const { t } = useI18n();

    const fileInput = ref<HTMLInputElement>();
    const inputKey = ref(Date.now());
    const tableRef = ref();
    const showImportModal = computed({
      get() {
        return props.modelValue;
      },
      set(value) {
        emit("update:modelValue", value);
      }
    });

    const gridOption = reactive<PropDefines>({
      isServerPage: false,
      showCheckbox: true,
      showExportBtn: false,
      columns: [
        {
          field: "device_model",
          title: "device_manage.form.device_model",
          minWidth: 150,
          align: "center"
        },
        {
          field: "device_id",
          title: "device_manage.form.device_id",
          minWidth: 150,
          align: "center"
        },
        {
          field: "business_id",
          title: "device_manage.form.business_id",
          minWidth: 150,
          align: "center"
        },
        {
          field: "material",
          title: "device_manage.import.material_color",
          minWidth: 150,
          align: "center"
        },
        {
          field: "itemStatus",
          title: "device_manage.import.error_status",
          minWidth: 70,
          align: "center",
          slots: {
            default: "status_default"
          }
        },
        {
          field: "itemFailInfo",
          title: "device_manage.import.error_info",
          minWidth: 180,
          align: "center",
          showOverflow: false
        }
      ],
      actions: [],
      operateTools: [],
      dataSource: [],
      vxeTableConfig: {
        checkboxConfig: {
          checkMethod({ row }) {
            return row.itemStatus;
          }
        },
        pagerConfig: {
          enabled: false
        }
      }
    });

    const expandMergedCells = (worksheet, json) => {
      if (!worksheet["!merges"]) return;

      worksheet["!merges"].forEach(merge => {
        const startRow = merge.s.r;
        const endRow = merge.e.r;
        const startCol = merge.s.c;
        const endCol = merge.e.c;
        const cellValue = json[startRow][startCol];

        for (let row = startRow; row <= endRow; row++) {
          for (let col = startCol; col <= endCol; col++) {
            if (!json[row]) json[row] = [];
            json[row][col] = cellValue;
          }
        }
      });
    };

    const checkExcelData = (rawData: string[][]) => {
      if (!rawData || rawData.length < 2) {
        proxy.$message.error(t("device_manage.import.table_error"));
        return false;
      }

      const needField = [
        t("device_manage.form.device_model"),
        t("device_manage.form.device_id")
      ];
      const havaField = rawData[0];
      for (let i = 0; i < needField.length; i++) {
        let status = false;
        for (let item of havaField) {
          if (needField[i] == item) {
            status = true;
            break;
          }
        }
        if (!status) {
          proxy.$message.error(
            t("device_manage.import.column_missing", { column: needField[i] })
          );
          return false;
        }
      }

      return true;
    };

    const retMatchLength = (initial: string[], value: string) => {
      let isMatch = false;
      for (let i = 0; i < initial.length; i++) {
        if (value.substring(0, initial[i].length) === initial[i]) {
          isMatch = true;
          break;
        }
      }
      return isMatch;
    };

    const handleExcelData = (rawData: string[][]) => {
      const dataSource = [];
      const haveField = [
        "index",
        "device_model",
        "device_id",
        "business_id",
        "material",
        "note"
      ];
      const filterData = rawData.filter(item => {
        return item.length > 0;
      });
      for (let i = 1; i < filterData.length; i++) {
        const json = {};
        const rowValue = rawData[i];

        for (let j = 0; j < haveField.length; j++) {
          const key = haveField[j];
          json[key] = rowValue[j] ?? "";
        }

        let itemStatus = true;
        const deviceFailInfo = [];

        // region 设备型号
        const deviceModel = json[haveField[1]];
        if (deviceModel.length < 5 || deviceModel.length > 100) {
          deviceFailInfo.push(t("device_manage.form.device_model_length"));
          itemStatus = false;
        }
        if (deviceModel.indexOf("ATT-") == -1) {
          deviceFailInfo.push(t("device_manage.form.device_model_format"));
          itemStatus = false;
        } else {
          const rawValueSplit = deviceModel.split("ATT-");
          const splitValue = rawValueSplit[1];
          if (splitValue.length < 2) {
            deviceFailInfo.push(
              t("device_manage.form.device_model_length_short")
            );
            itemStatus = false;
          } else {
            const deviceModelSplit = deviceModel.split("ATT-");
            json["device_type"] = "";
            for (const key in DEVICE_TYPE_MATCH) {
              const devKey = deviceModelSplit[1].substring(0, key.length);
              if (devKey === key) {
                json["device_type"] = DEVICE_TYPE_MATCH[key];
              }
            }
            if (!json["device_type"]) {
              deviceFailInfo.push(t("device_manage.form.device_model_letter"));
              itemStatus = false;
            }
          }
        }
        // endregion

        // region 设备编号
        const deviceId = json[haveField[2]];
        if (deviceId.length < 5 || deviceId.length > 100) {
          deviceFailInfo.push(t("device_manage.form.device_id_length"));
          itemStatus = false;
        }
        if (deviceId.indexOf("ATT-") == -1) {
          deviceFailInfo.push(t("device_manage.form.device_id_format"));
          itemStatus = false;
        } else {
          const rawValueSplit = deviceId.split("ATT-");
          const splitValue = rawValueSplit[1];
          if (splitValue.length < 2) {
            deviceFailInfo.push(t("device_manage.form.device_id_length_short"));
            itemStatus = false;
          } else {
            // const idInitial = ["U", "V", "K", "E", "tp", "BAT", "JU"];
            const idVal = deviceId.split("ATT-")[1] ?? "";
            if (!retMatchLength(DEVICE_ID_LIST, idVal)) {
              deviceFailInfo.push(t("device_manage.form.device_id_letter"));
              itemStatus = false;
            }
          }
        }
        //   endregion

        //   region 商家ID
        if (json["device_type"] == DEVICE_TYPE_ENUM.MIXING_MAT) {
          const storeId = json[haveField[3]];
          json["business_id"] = storeId;
          if (storeId != undefined && storeId != "" && !RegInt(storeId)) {
            deviceFailInfo.push(t("device_manage.import.business_id_error"));
            itemStatus = false;
          }
        }
        json["itemFailInfo"] = Unique(deviceFailInfo).join("\n");
        json["itemStatus"] = itemStatus;
        // endregion

        dataSource.push(json);
      }
      gridOption.dataSource = dataSource;
      setSelectRow(dataSource, true);
    };

    const fileChanged = () => {
      console.log(fileInput.value?.files);
      const file = fileInput.value.files[0];
      if (file) {
        const reader = new FileReader();
        reader.onload = e => {
          const data = new Uint8Array(e.target.result as ArrayBuffer);
          const workbook = XLSX.read(data, { type: "array" });
          const firstSheetName = workbook.SheetNames[0];
          const worksheet = workbook.Sheets[firstSheetName];
          const json = XLSX.utils.sheet_to_json(worksheet, {
            header: 1
          }) as string[][];
          console.log(json, worksheet);
          if (checkExcelData(json)) {
            handleExcelData(json);
          }
          inputKey.value = Date.now();
        };
        reader.readAsArrayBuffer(file);
      }
    };

    const setSelectRow = (rows: Record<string, any>[], checked: boolean) => {
      const $table = tableRef.value;
      if ($table) {
        console.log($table.vxeGridRef, rows);
        nextTick(() => {
          $table.vxeGridRef.setCheckboxRow(rows, checked);
        });
      }
    };

    const handleConfirm = () => {
      const dataSource = tableRef.value.getCheckboxRecords();
      if (!dataSource.length) {
        proxy.$message.error(t("device_manage.import.select_data"));
        return;
      }

      const content = dataSource.map((item: Record<string, string>) => {
        return {
          device_model: item.device_model,
          device_id: item.device_id,
          device_type: item.device_type,
          business_id: item.business_id
        };
      });

      addDeviceEnterList({ jsonData: JSON.stringify(content) }).then(res => {
        if (res.data?.length) {
          gridOption.dataSource = res.data.map(v => {
            v["itemStatus"] = false;
            v["itemFailInfo"] = t("device_manage.import.duplicate_import");
            return v;
          });
        } else {
          proxy.$message.success(t("device_manage.import.import_success"));
          showImportModal.value = false;
          emit("confirm");
        }

        /* 导入成功后，如果指定了商家默认激活 */
        handleActiveDevice(dataSource);
      });
    };

    // 单设备激活
    const deviceActivationData = (device_id: string, business_id: string) => {
      return new Promise((resolve, reject) => {
        deviceActivation({ device_id, business_id })
          .then(res => {
            resolve({
              code: 200,
              message: t("device_manage.import.activation_success")
            });
          })
          .catch(d => {
            reject({ code: d.code, message: d.message, device_id });
          });
      });
    };

    function handleActiveDevice(rows: Record<string, any>[]) {
      const operateArray = [];
      for (const row of rows) {
        if (row.business_id) {
          operateArray.push(
            deviceActivationData(row.device_id, row.business_id)
          );
        }
      }
      if (operateArray.length) {
        Promise.allSettled(operateArray)
          .then(results => {
            let activeNum = 0;
            results.forEach(result => {
              if (result.status === "fulfilled") {
                activeNum++;
              } else if (result.status === "rejected") {
                const curRow = rows.find(
                  v => v.device_id === result.reason.device_id
                );
                curRow["itemStatus"] = false;
                curRow["itemFailInfo"] = result.reason.message;
                gridOption.dataSource.push(curRow);
              }
            });
            if (activeNum) {
              proxy.$message.success(
                t("device_manage.import.activation_success")
              );
            }
          })
          .catch(d => {
            console.log(d);
          });
      }
    }

    const fileDownload = () => {
      const path = import.meta.env?.VITE_PUBLIC_PATH ?? "/admin/";
      window.location.href = location.origin + path + "/设备导入示例表.xlsx";
    };

    watch(
      () => props.modelValue,
      val => {
        if (!val) {
          gridOption.dataSource = [];
        }
      }
    );

    return {
      fileInput,
      inputKey,
      showImportModal,
      gridOption,
      tableRef,
      fileChanged,
      handleConfirm,
      fileDownload,
      t
    };
  }
});
</script>
